package com.gollum.web.service;

import com.gollum.common.enums.GollumStatus;
import com.gollum.common.enums.LogicalDeleteType;
import com.gollum.common.enums.SystemStatus;
import com.gollum.common.exception.BusinessException;
import com.gollum.common.utils.BeanUtils;
import com.gollum.common.utils.StringUtils;
import com.gollum.system.domain.response.LoginUser;
import com.gollum.system.domain.model.*;
import com.gollum.system.domain.response.SysPostResponse;
import com.gollum.system.domain.response.SysUserResponse;
import com.gollum.system.service.SysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 自定义登录逻辑
 *
 * @author Herther
 * @version 1.0.0
 * @createTime 2022年08月24日 21:41:00
 */
@Service
public class UserDetailsServiceimpl implements org.springframework.security.core.userdetails.UserDetailsService {

    private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceimpl.class);

    @Autowired
    protected SysUserService sysUserService;

    /**
     * 登录处理
     *
     * @param username 用户名
     * @return UserDetails
     * @auther: Herther
     * @version 1.0.0
     * @date: 2022/8/26 23:02
     */
    @Override
    @Transactional
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SysUser sysUser = sysUserService.getUserByUsername(username);
        if (StringUtils.isNull(sysUser)) {
            log.error("登录用户：{} 不存在.", username);
            throw new BusinessException("登录的用户名：" + username + "不存在");
        } else if (LogicalDeleteType.DELETED.isDelete(sysUser.getHasDel())) {
            log.error("登录用户：{} 已被删除.", username);
            throw new BusinessException("对不起，您的账号：" + username + " 已被删除");
        } else if (GollumStatus.DISABLE.isStatus(sysUser.getStatus())) {
            log.error("登录用户：{} 已被停用.", username);
            throw new BusinessException("对不起，您的账号：" + username + " 已停用");
        }
        //获取权限列表
        Set<String> permission = getPermission(sysUser);

        return createLoginUser(sysUser,permission);
    }


    /**
     *  创建用户，查找部门与职位放入到loginUser中
     *
     * @param
     * @return
     * @auther: Herther
     * @version 1.0.0
     * @date: 2022/8/27 22:00
     */
    public UserDetails createLoginUser(SysUser user, Set<String> permission) {
        //拷贝职位
        List<SysPost> sysPosts = user.getSysPosts();
        List<SysPostResponse> sysPostResponsBodies = BeanUtils.copyToList(sysPosts, SysPostResponse.class);

        //拷贝用户对象
        SysUserResponse sysUserResponse = new SysUserResponse();
        BeanUtils.copyBeanProp(user, sysUserResponse);

        //职位设置到Response
        sysUserResponse.setSysPosts(sysPostResponsBodies);

        return new LoginUser(sysUserResponse.getId(), sysUserResponse, permission);
    }

    /**
     *  获取权限
     *
     * @param sysUser 数据库查询出来的持久态用户实体
     * @return
     * @auther: Herther
     * @version 1.0.0
     * @date: 2022/8/27 0:13
     */
    public Set<String> getPermission(SysUser sysUser) {
        Boolean isAdmin = sysUser.isAdmin();
        Set<String> perms = new HashSet<String>();
        if (isAdmin) {
            perms.add("*:*:*");
        } else {
            perms.addAll(getMenusPermis(sysUser));
        }
        return perms;
    }

    /**
     * 获取菜单字符串，根据角色那些
     *
     * @param sysUser 数据库查询出来的持久态用户实体
     * @auther: Herther
     * @version 1.0.0
     * @date: 2022/8/27 0:11
     */
    public Set<String> getMenusPermis(SysUser sysUser){
        List<SysRole> roles = sysUser.getRoles();
        Set<String> permsSet = new HashSet<>();
        roles.forEach(role->{
          if (SystemStatus.NORMAL.isStatus(role.getStatus())){
              List<SysMenu> menus = role.getMenus();
              for (SysMenu menu : menus) {
                  if (StringUtils.isNotEmpty(menu.getPerms()) && SystemStatus.NORMAL.isStatus(menu.getStatus())){
                      permsSet.addAll(Arrays.asList(menu.getPerms().trim().split(",")));
                  }
              }
          }
        });
        return permsSet;
    }


}
